﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IRC.IRepairClouds.DataLayer
{
    public abstract class LazzyLoaderWeakBase<T> where T : class
    {
        private WeakReference<T> _value;
        private bool _isNull = false;

        public LazzyLoaderWeakBase()
        {
        }

        public bool IsLoaded
        {
            get { return _isNull || (_value != null && _value.IsAlive); }
        }

        public T Value
        {
            get
            {
                T res = null;
                if (!_isNull && (_value == null || (res = _value.Target) == null)) {
                    res = GetValue();
                    if (res != null)
                        _value = new WeakReference<T>(res);
                    else
                        _isNull = true;
                }
                return res;
            }
        }

        protected abstract T GetValue();

        public override string ToString()
        {
            return this.Value.ToString();
        }

        public static explicit operator T(LazzyLoaderWeakBase<T> value)
        {
            return value.Value;
        }
    }

    public class LazzyLoaderWeak<T> : LazzyLoaderWeakBase<T> where T : class
    {
        private Func<T> _getValue;

        public LazzyLoaderWeak(Func<T> getValue)
        {
            _getValue = getValue;
        }

        protected override T GetValue()
        {
            return _getValue();
        }
    }

    public class LazzyLoaderWeak<T, TC> : LazzyLoaderWeakBase<T> where T : class
    {
        private Func<TC, T> _getValue;
        private TC _context;

        public LazzyLoaderWeak(TC context, Func<TC, T> getValue)
        {
            _context = context;
            _getValue = getValue;
        }

        public TC Context
        {
            get { return _context; }
        }

        protected override T GetValue()
        {
            return _getValue(_context);
        }
    }
}
